// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <cstdint>

#include "coin2/base/time.h"

namespace impl {

// class NonceManager
// - thread unsafe
class NonceManager {
  class Nonce {
   public:
    Nonce() : nonce_(GetCurrentTimestamp() / 1000), count_(0) {}
    ~Nonce() = default;
    Nonce(const Nonce&) = delete;
    Nonce& operator=(const Nonce&) = delete;

    int64_t Get() {
      ++ count_;

      if (count_ == SYNC_NONCE_WITH_CLOCK_COUNT) {
        count_ = 0;
        nonce_ = std::max(GetCurrentTimestamp() / 1000, nonce_ + 1);
      } else {
        ++ nonce_;
      }

      return nonce_;
    }

   private:
    constexpr static int64_t SYNC_NONCE_WITH_CLOCK_COUNT = 100;

    int64_t nonce_;
    int64_t count_;
  };

 public:
  static int64_t Get() {
    static Nonce nonce;
    return nonce.Get();
  }
};

}  // namespace impl
